home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / Base / Int64.cp < prev    next >
Encoding:
Text File  |  1996-02-19  |  5.8 KB  |  235 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        Int64.c
  3.  
  4.     Contains:    64-bit math class
  5.  
  6.     Written by:    Dave Owens, tweeked by Andy Nicholas and Chris Bingham
  7.  
  8.     Copyright:    © 1994-1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.          <3>     3/20/95    andy    
  11. */
  12.  
  13. #ifdef MWTRACEBACKTABLES
  14. #pragma traceback on
  15. #endif
  16.  
  17. #include "Int64.h"
  18.  
  19. #pragma segment LookupSizes
  20.  
  21. //========================================================================================
  22. // CLASS Int64
  23. //========================================================================================
  24.  
  25. //----------------------------------------------------------------------------------------
  26. // Int64::IntuitOtherOperand: 
  27. //
  28. // IntuitOtherOperand
  29. //
  30. // This function decodes the input data and makes sure that it is packaged into
  31. // an Int64.
  32. //----------------------------------------------------------------------------------------
  33. const Int64* Int64::IntuitOtherOperand(SInt16 operation, const void* input, Int64* otherStorage)
  34.     {
  35.     int type = operation & typeMask;
  36.     if (type == typeOtherIsInt64)
  37.         return (const Int64*) input;
  38.  
  39.     otherStorage->fSInt64.hi = 0;
  40.  
  41.     switch (type)
  42.         {
  43.         case typeOtherIsInt:
  44.             {
  45.             if (*(const int*)input < 0)
  46.                 otherStorage->fSInt64.hi =  -1;
  47.                 
  48.             otherStorage->fSInt64.lo = *(const int*) input;
  49.             break;
  50.             }
  51.         case typeOtherIsLong:
  52.             {
  53.             if (*(const SInt32*)input < 0)
  54.                 otherStorage->fSInt64.hi =  -1;
  55.                 
  56.             otherStorage->fSInt64.lo = *(const UInt32*) input;
  57.             break;
  58.             }
  59.         
  60.         default:
  61.             otherStorage->fSInt64.lo = *(const UInt32*) input;
  62.         }
  63.         
  64.     return otherStorage;
  65.     } // Int64::IntuitOtherOperand 
  66.  
  67.  
  68. //----------------------------------------------------------------------------------------
  69. // Int64::Operation: 
  70. //----------------------------------------------------------------------------------------
  71. Int64 Int64::Operation(SInt16 operation, const void* input) const
  72.     {
  73.     Int64 sourceStorage;
  74.  
  75.     Int64 main;
  76.     main.fSInt64.hi = fSInt64.hi;
  77.     main.fSInt64.lo  = fSInt64.lo;
  78.  
  79.     const Int64* other = IntuitOtherOperand(operation, input, &sourceStorage);
  80.     UInt32 temp;
  81.         
  82.     switch (operation & verbMask)
  83.         {
  84.         case verbAssign:
  85.             {
  86.             main.fSInt64.hi = other->fSInt64.hi;
  87.             main.fSInt64.lo = other->fSInt64.lo;
  88.             }
  89.             break;
  90.             
  91.         case verbAdd:
  92.             {
  93.             temp = main.fSInt64.lo + other->fSInt64.lo;
  94.             if ((temp < main.fSInt64.lo) && (temp < other->fSInt64.lo))
  95.                 ++main.fSInt64.hi;                        // catch overflow
  96.             main.fSInt64.lo = temp;
  97.             main.fSInt64.hi += other->fSInt64.hi;    
  98.             }
  99.             break;
  100.  
  101.         case verbSubtract:
  102.             {
  103.             if (other->fSInt64.lo > main.fSInt64.lo)        // catch underflow
  104.                 --main.fSInt64.hi;
  105.             main.fSInt64.lo -= other->fSInt64.lo;
  106.             main.fSInt64.hi -= other->fSInt64.hi;
  107.             }
  108.             break;
  109.  
  110.         //
  111.         // ••• this code needs to be replaced by something that works,
  112.         //        preferably a call to the 64-bit math library!
  113.         //
  114.         case verbMultiply:
  115.             {
  116.             if ((main == Int64(0L) ) || (*other == Int64(0L) ))
  117.                 main = 0;
  118.             else
  119.                 {
  120.                 // assumes a maximum multiply of 48 bits * 31 bits
  121.                 UInt16 a3 = (main.fSInt64.hi & 0xFFFF);
  122.                 UInt16 a2 = (main.fSInt64.lo & 0xFFFF0000) >> 16;
  123.                 UInt16 a1 = (main.fSInt64.lo & 0xFFFF);
  124.                 UInt16 b2 = (other->fSInt64.lo & 0xFFFF0000) >> 16;
  125.                 UInt16 b1 = (other->fSInt64.lo & 0xFFFF);
  126.                 
  127.                 main = (UInt32) ((a3 * b2));
  128.                 main <<= 16;
  129.                 main += (UInt32) ((a3 * b1) + (a2 * b2));
  130.                 main <<= 16;
  131.                 main += (UInt32) ((a2 * b1) + (a1 * b2));
  132.                 main <<= 16;
  133.                 main += (UInt32)(a1 * b1);
  134.                 }
  135.             }
  136.             break;
  137.  
  138.         //
  139.         // ••• this code needs to be replaced by something that works,
  140.         //        preferably a call to the 64-bit math library!
  141.         //
  142.         case verbDivide:
  143.             {
  144.             if ((main == Int64(0L) ) || (*other == Int64(0L) ))
  145.                 main = 0;
  146.             else
  147.                 {
  148. //                other->fSInt64.lo is the denominator
  149.                 SInt32 numerator = main.fSInt64.hi;
  150.                 Int64 times;
  151.                 times.fSInt64.hi = numerator / other->fSInt64.lo;
  152.                 
  153.                 numerator -= times.fSInt64.hi * other->fSInt64.lo;
  154.                 numerator = (numerator << 16) | (main.fSInt64.lo >> 16);
  155.                 times.fSInt64.lo = numerator / other->fSInt64.lo;
  156.     
  157.                 numerator -= times.fSInt64.lo * other->fSInt64.lo;
  158.                 numerator = (numerator << 16) | (main.fSInt64.lo & 0xFFFF);
  159.                 times.fSInt64.lo <<= 16;
  160.                 times.fSInt64.lo += numerator / other->fSInt64.lo;
  161.  
  162.                 main.fSInt64.hi = times.fSInt64.hi;
  163.                 main.fSInt64.lo = times.fSInt64.lo;
  164.                 }
  165.             }
  166.             break;
  167.  
  168.         case verbShiftRight:
  169.             {
  170. //            ASSERT(*other < 64);
  171.             temp = other->fSInt64.lo;
  172.             main.fSInt64.lo =  (main.fSInt64.hi << (32 - temp)) | (main.fSInt64.lo >> temp);
  173.             main.fSInt64.hi = main.fSInt64.hi >> temp;
  174.             }
  175.             break;
  176.  
  177.         case verbShiftLeft:
  178.             {
  179. //            ASSERT(*other < 64);
  180.             temp = other->fSInt64.lo;
  181.             main.fSInt64.hi = (main.fSInt64.hi << temp) | (main.fSInt64.lo >> (32 - temp));
  182.             main.fSInt64.lo = main.fSInt64.lo << temp;
  183.             }
  184.             break;
  185.  
  186.         default:
  187. //            ASSERT(false);
  188.             break;
  189.         }
  190.         
  191.     return main;
  192.     }
  193.  
  194. //----------------------------------------------------------------------------------------
  195. // Int64::Comparison: 
  196. //----------------------------------------------------------------------------------------
  197. Boolean    Int64::Comparison(SInt16 comparison, const void* input) const
  198.     {
  199.     Int64 otherStorage;
  200.  
  201.     const Int64* other = IntuitOtherOperand(comparison, input, &otherStorage);
  202.     Boolean result = false;
  203.     Boolean negateResult = false;
  204.     
  205.     switch (comparison & cmpMask)
  206.         {
  207.         case cmpNotEqual:
  208.             negateResult = true;
  209.         case cmpEqual:
  210.             result = (fSInt64.hi == other->fSInt64.hi) && (fSInt64.lo == other->fSInt64.lo);
  211.             break;
  212.         
  213.         case cmpGreaterOrEqual:
  214.             negateResult = true;
  215.         case cmpLess:
  216.             result = (fSInt64.hi < other->fSInt64.hi) ||
  217.                     ((fSInt64.hi == other->fSInt64.hi) && (fSInt64.lo < other->fSInt64.lo));
  218.             break;
  219.  
  220.         case cmpLessOrEqual:
  221.             negateResult = true;
  222.         case cmpGreater:
  223.             result = (fSInt64.hi > other->fSInt64.hi) ||
  224.                     ((fSInt64.hi == other->fSInt64.hi) && (fSInt64.lo > other->fSInt64.lo));
  225.             break;
  226.             
  227.         default:
  228. //            ASSERT(false);
  229.             break;
  230.         }
  231.     
  232.     return result ^ negateResult;
  233.     } // Int64::Comparison 
  234.  
  235.